#include "SDRedisHelper.h"
#include "SDLog.h"
#include "sw/redis++/redis++.h"
#include <memory>

void redisXXLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string lock_sign, uint32_t lock_sec)
{
    redis->setex(lock, std::chrono::seconds(lock_sec),lock_sign);
}

void redisXXUnlock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string lock_sign)
{
    auto lock_val = redis->get(lock);
    if(lock_val  && (*lock_val) == lock_sign)
        redis->del(lock);
}

std::string redisXXGetStringLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string def)
{
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }

    auto val_got = redis->get(key);

    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
    return val_got ? *val_got : def;
}

void  redisXXSetStringLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string value)
{
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }

    redis->set(key, value);

    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}


void redisXXHashDelFieldLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string field)
{
    std::string lock_at;

    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }
    redis->hdel(key, field);
    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}


void redisXXHashSetFieldLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string field,std::string value)
{
    std::string lock_at;

    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }
    redis->hset(key, field, value);
    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}

std::string  redisXXHashGetFieldLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string filed,std::string def)
{
    std::string lock_at;
    std::string val = def;

    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }

    auto ret_val = redis->hget(key, filed);
    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
    if(ret_val) 
        val =  *ret_val;

    return  val; 
}

void redisXXHashGetAllFieldLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::unordered_map<std::string, std::string> &m)
{
    m.clear();
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }
    redis->hgetall(key, std::inserter(m, m.begin()));
    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}

void  redisXXDeleteLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key)
{
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }
    
    redis->del(key);

    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}

void  redisXXListRPushLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::string value)
{
    std::vector<std::string> vec = {value};
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }

    redis->rpush(key,vec.begin(),vec.end());

    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}

void redisXXListAllLock(std::shared_ptr<sw::redis::Redis> redis,std::string lock,std::string key,std::vector<std::string>& vec,bool del)
{
    vec.clear();
    std::string lock_at;
    if(!lock.empty()){
        lock_at =  std::to_string((uint64_t)lock.data());
        redisXXLock(redis,lock,lock_at, 2);
    }   
    redis->lrange(key, 0, -1, std::back_inserter(vec));
    if(del)
        redis->del(key);
    if(!lock.empty()){
        redisXXUnlock(redis, lock, lock_at);
    }
}